import React, {useEffect, useState} from "react";
import ReactDOM from "react-dom";
import "./App.less"; 
import G6 from "@antv/g6";
import defaultImg from "./static/img/default.jpg";
import {getMenu} from "./menu"
import "./menu.less"
import {addNode} from "./pages/common/nodeUtils";
import {addEdge} from "./pages/common/edgeUtils";
import {pushStack, undo, redo} from "./pages/common/undoRedoUtil";
import {groupNodes, unGroupNodes} from "./pages/common/groupUtils"
import {gridLayout, dagreLayout, directionLayout} from "./pages/common/layoutUtils";
import "./pages/common/behavior/click-select-edge";
import "./pages/common/behavior/brush-select-right";
import "./pages/common/node/person-node";
import {message} from "antd";

function App() {
    let ref = React.useRef(null);
    let graph = React.useRef(null);
    let [nodePosition, setNodePosition] = useState({});
    let [nodeIndex, setNodeIndex] = useState(0);
    let [undoOrRedo, setUndoOrRedo] = useState({
        undo: 0,
        redo: 0
    });
    const selectedStates = 'selected';

    // const data = {
    //     nodes: [
    //         {
    //             id: "1",
    //             label: "公司1",
    //             size: [40, 40],
    //             img: defaultImg,
    //             type: "person-node"
    //         },
    //         {
    //             id: "2",
    //             label: "公司2",
    //         },
    //         {
    //             id: "3",
    //             label: "公司3",
    //         },
    //         {
    //             id: "4",
    //             label: "公司4",
    //         },
    //         {
    //             id: "5",
    //             label: "公司5",
    //         },
    //         {
    //             id: "6",
    //             label: "公司6",
    //         },
    //         {
    //             id: "7",
    //             label: "公司7",
    //         },
    //         {
    //             id: "8",
    //             label: "公司8",
    //         },
    //         {
    //             id: "9",
    //             label: "公司9",
    //         },
    //         {
    //             id: "10",
    //             label: "公司10",
    //         },
    //         {
    //             id: "11",
    //             label: "公司11",
    //         },
    //     ],
    //     edges: [
    //         {
    //             source: "1",
    //             target: "2",
    //             data: {
    //                 type: "name1",
    //                 amount: "100,000,000,00 元",
    //                 date: "2019-08-03",
    //             },
    //         },
    //         {
    //             source: "1",
    //             target: "3",
    //             data: {
    //                 type: "name2",
    //                 amount: "100,000,000,00 元",
    //                 date: "2019-08-03",
    //             },
    //         },
    //         {
    //             source: "2",
    //             target: "4",
    //             data: {
    //                 type: "name1",
    //                 amount: "100,000,000,00 元",
    //                 date: "2019-08-03",
    //             },
    //         },
    //         {
    //             source: "5",
    //             target: "6",
    //             data: {
    //                 type: "name2",
    //                 amount: "100,000,000,00 元",
    //                 date: "2019-08-03",
    //             },
    //         },
    //         {
    //             source: "3",
    //             target: "4",
    //             data: {
    //                 type: "name3",
    //                 amount: "100,000,000,00 元",
    //                 date: "2019-08-03",
    //             },
    //         },
    //         {
    //             source: "4",
    //             target: "7",
    //             data: {
    //                 type: "name2",
    //                 amount: "100,000,000,00 元",
    //                 date: "2019-08-03",
    //             },
    //         },
    //         {
    //             source: "1",
    //             target: "8",
    //             data: {
    //                 type: "name2",
    //                 amount: "100,000,000,00 元",
    //                 date: "2019-08-03",
    //             },
    //         },
    //         {
    //             source: "1",
    //             target: "9",
    //             data: {
    //                 type: "name3",
    //                 amount: "100,000,000,00 元",
    //                 date: "2019-08-03",
    //             },
    //         },
    //         {
    //             source: "9",
    //             target: "10",
    //             data: {
    //                 type: "name3",
    //                 amount: "100,000,000,00 元",
    //                 date: "2019-08-03",
    //             },
    //         },
    //         {
    //             source: "9",
    //             target: "11",
    //             data: {
    //                 type: "name3",
    //                 amount: "100,000,000,00 元",
    //                 date: "2019-08-03",
    //             },
    //         },
    //     ],
    // };


    const data = {
        nodes: [
            {
                id: "18",
                label: "公司18",
            },
            {
                id: "1",
                label: "公司1",
                size: [40, 40],
                img: defaultImg,
                type: "person-node"
            },
            {
                id: "2",
                label: "公司2",
            },
            {
                id: "3",
                label: "公司3",
            },
            {
                id: "4",
                label: "公司4",
            },
            {
                id: "5",
                label: "公司5",
            },
            {
                id: "6",
                label: "公司6",
            },
            {
                id: "7",
                label: "公司7",
            },
            {
                id: "8",
                label: "公司8",
            },
            {
                id: "9",
                label: "公司9",
            },
            {
                id: "10",
                label: "公司10",
            },
            {
                id: "11",
                label: "公司11",
            },
            {
                id: "12",
                label: "公司12",
            },
            {
                id: "13",
                label: "公司13",
            },
            {
                id: "14",
                label: "公司14",
            },
            {
                id: "15",
                label: "公司15",
            },
            {
                id: "16",
                label: "公司16",
            },
            {
                id: "17",
                label: "公司17",
            },
            
        ],
        edges: [
            {
                source: "1",
                target: "2",
                
            },
            {
                source: "1",
                target: "3",
            },
            {
                source: "1",
                target: "4",
                
            },
            {
                source: "1",
                target: "5",
            },
            {
                source: "2",
                target: "6",
                
            },
            {
                source: "2",
                target: "7",
            },
            {
                source: "3",
                target: "8",
            },
            {
                source: "3",
                target: "9",
                
            },
            {
                source: "3",
                target: "10",
            },
            {
                source: "3",
                target: "11",
            },
            {
                source: "4",
                target: "12",
            },
            {
                source: "4",
                target: "13",
            },
            {
                source: "4",
                target: "14",
            },
            {
                source: "4",
                target: "15",
            },
            {
                source: "4",
                target: "16",
            },
            {
                source: "4",
                target: "17",
            },
            {
                source: "4",
                target: "18",
            },
            {
                source: "4",
                target: "12",
            },
        ],
    };
    
    // 初始化关系图
    useEffect(() => {
        const contextMenu = new G6.Menu({
            getContent(evt) {
              console.log('event', evt);
              const list = [
                {
                    id: 1,
                    title: "最近行为",
                    subMenu: [
                     {
                         id: 1,
                         title: "最近行为"
                     },
                     {
                         id: 2,
                         title: "深入探索"
                     },]
                },
                {
                    id: 2,
                    title: "深入探索",
                    handleClick: (e) => {
                        console.log("深入探索")
                    }
                },
                {
                    id: 3,
                    title: "自定义",
                    subMenu: [
                     {
                         id: 1,
                         title: "最近行为",
                         handleClick: () => {
                             console.log("最近行为")
                         }

                     },
                     {
                         id: 2,
                         title: "深入探索"
                     },
                     {
                         id: 3,
                         title: "自定义"
                     }
                     
                 ]
                },{
                    id: 4,
                    title: "删除"
                },{
                    id: 5,
                    title: "选中"
                },{
                    id: 6,
                    title: "筛选"
                }
            ]
              return getMenu(list);
            },
            // handleMenuClick: (target, item) => {
            // //   console.log(target, item);
            // },
            // offsetX: -((500 - item.width)/2 + item.width)
            // 500是菜单宽度 item.width为node宽度
            // offsetX: -(250 - 40/2),
            // 现在为传入元素宽度
            offsetX: 40,
            // offsetY: -((500 - item.height)/2 + item.height)
            // offsetY: -(250 - 40/2) -40,
            // 现在为传入元素高度
            offsetY: 40,
            // the types of items that allow the menu show up
            // 在哪些类型的元素上响应
            itemTypes: ['node'],
          });

        console.log(graph.current)

        // let ox = [{x: 1}, {x: 2}];
        // let o = {x:2}
        // console.log(JSON.stringify(ox))
        // console.log(JSON.stringify(o))
        // console.log(_.find(ox, o));

        if (!graph.current) {
            graph.current = new G6.Graph({
                container: ReactDOM.findDOMNode(ref.current),
                width: 1200,
                height: 800,
                linkCenter: true,
                plugins: [contextMenu],
                enabledStack: true,
                maxStep: 5,
                // animate: true,
                modes: {
                    // 默认：
                    // 节点：拖动 选中
                    // 画布：拖动 缩放
                    // 框选：
                    default: [{
                        type: "brush-select-right",
                        includeEdges: true
                    }, "drag-canvas", "zoom-canvas", {type: "drag-node", updateEdge: true}, {
                        type: "click-select",
                        trigger: 'ctrl'
                    }, "click-select-edge"],
                    brush: [
                        {
                            type: 'brush-select',
                            trigger: 'drag',
                            includeEdges: true
                        }, {
                            type: "click-select",
                            trigger: 'ctrl'
                        }, {
                            type: "brush-select-right",
                            includeEdges: true
                        }, "click-select-edge"
                    ]
                },
                layout: {
                    type: "dagre",
                    // rankdir: 'TB', // 可选，默认为/图的中心
                    // align: 'DL', // 可选
                    // nodesep: 20, // 可选
                    // ranksep: 50, // 可选
                    // controlPoints: true, // 可选
                },
                defaultNode: {
                    type: "rect",
                    labelCfg: {
                        style: {
                            fill: "#000000A6",
                            fontSize: 10,
                        },
                        position: 'bottom',
                    },
                    style: {
                        stroke: "#72CC4A",
                        width: 40,
                        height: 40,
                    }
                },
                defaultEdge: {
                    style: {
                        stroke: "rgba(100,100,100,0.6)", // 必须设置样式，否则item.ts-》setOriginStyle方法导致使用更新后的样式
                        lineWidth: 2,
                        lineAppendWidth: 6
                    }
                },
                nodeStateStyles: {
                    hover: {
                        // stroke: "#2635cc",
                        cursor: 'pointer'
                    },
                    selected: {
                        stroke: "#2635cc"
                    }
                },
                edgeStateStyles: {
                    hover: {
                        // stroke: "#2635cc",
                        cursor: 'pointer'
                    },
                    selected: {
                        stroke: "#2635cc"
                    }
                }
                // defaultEdge: {
                //     type: "polyline",
                // },
            });
        }
        graph.current.data(data);
        graph.current.render();

        // 屏蔽右键浏览器默认
        graph.current.on('node:contextmenu', (evt) => {
            evt.preventDefault();

        })
        graph.current.on('edge:contextmenu', (evt) => {
            evt.preventDefault();
        })
        graph.current.on('canvas:contextmenu', (evt) => {
            evt.preventDefault();
        })

        // 鼠标进入节点
        graph.current.on('node:mouseenter', (e) => {

            const nodeItem = e.item; // 获取鼠标进入的节点元素对象
            graph.current.setItemState(nodeItem, 'hover', true); // 设置当前节点的 hover 状态为 true
        });

        // 鼠标离开节点
        graph.current.on('node:mouseleave', (e) => {
            const nodeItem = e.item; // 获取鼠标离开的节点元素对象
            graph.current.setItemState(nodeItem, 'hover', false); // 设置当前节点的 hover 状态为 false
        });

        // 鼠标进入线
        graph.current.on('edge:mouseenter', (e) => {
            const edgeItem = e.item; // 获取鼠标进入的节点元素对象
            graph.current.setItemState(edgeItem, 'hover', true); // 设置当前节点的 hover 状态为 true
        });

        // 鼠标离开线
        graph.current.on('edge:mouseleave', (e) => {
            const edgeItem = e.item; // 获取鼠标离开的节点元素对象
            graph.current.setItemState(edgeItem, 'hover', false); // 设置当前节点的 hover 状态为 false
        });

        // graph.current.on('mouseup', (evt) => {
        //     console.log(evt)
        // })

        // 设置插入点位置
        let middleX = Number((graph.current.getWidth() / 2).toFixed(0));
        let middleY = Number((graph.current.getHeight() / 2).toFixed(0));

        setNodePosition({x: middleX, y: middleY});

        // 快捷方式
        document.addEventListener("keydown", keyOperation);
    }, []);

    /**
     * 键盘操作
     * 默认删除点的同时会删除线，所以必须先删除线，再删除点
     * @param e
     */
    const keyOperation = (e) => {
        if (e.keyCode === 8 || e.keyCode === 46) {
            let deleteEdgeModels = [];
            let deleteNodeModels = [];
            // 获取选中点
            const selectedEdges = graph.current.findAllByState('edge', selectedStates);
            const selectedNodes = graph.current.findAllByState('node', selectedStates);
            let itemTemp = {};
            selectedEdges.forEach(item => {
                itemTemp = item.getModel();
                itemTemp.itemType = 'edge';
                deleteEdgeModels.push(itemTemp);

                graph.current.removeItem(item, false);
            })

            selectedNodes.forEach(item => {
                itemTemp = item.getModel();
                itemTemp.itemType = 'node';
                deleteNodeModels.push(itemTemp);
                let nodeEdges = item.getEdges();
                nodeEdges.forEach(nodeEdge => {
                    itemTemp = nodeEdge.getModel();
                    itemTemp.itemType = 'edge';
                    deleteEdgeModels.push(itemTemp);
                })

                graph.current.removeItem(item, false);
            })

            // console.log(graph.current.getStackData());
            // graph.current.pushStack('delete', {
            //     before: {
            //         nodes: deleteNodeModels,
            //         // combps: [],
            //         edges: deleteEdgeModels,
            //         // groups: [],
            //     },
            //     after: {}
            // }, 'undo');
            let before = {
                nodes: deleteNodeModels,
                combos: [],
                edges: deleteEdgeModels,
                groups: [],
            }

            pushStack(graph.current, 'delete', before, []);

            setUndoOrRedo({
                undo: graph.current.getUndoStack().length,
                redo: graph.current.getRedoStack().length
            })
            // console.log(graph.current.getStackData());
        }

        // ctrl + z
        if (e.ctrlKey && e.keyCode === 90) {
            onUndo();
        }

        // TODO ctrl + a 全选
        if (e.ctrlKey && e.keyCode === 65) {
            let allNode = graph.current.getNodes();
            allNode.forEach(item => {
                let edges = item.getEdges();
                if (!item.hasState(selectedStates)) {
                    graph.current.setItemState(item, selectedStates, true);
                }

                edges.forEach(edge => {
                    if (!edge.hasState(selectedStates)) {
                        graph.current.setItemState(edge, selectedStates, true);
                    }
                })
            })
        }
    }

    /**
     * 框选模式切换
     */
    const onBrushSelect = () => {
        let currentMode = graph.current.getCurrentMode();
        console.log(currentMode);
        if (currentMode === 'brush') {
            graph.current.setMode('default');
        } else {
            graph.current.setMode('brush');
        }
    }

    /**
     * 添加点
     */
    const onAddNode = () => {
        nodeIndex += 1;
        setNodeIndex(nodeIndex);

        let nodeCfg = {
            id: 'node_' + nodeIndex,
            label: '公司_' + nodeIndex,
            img: defaultImg
        }
        addNode(graph.current, nodeCfg , nodeIndex, nodePosition);

        setUndoOrRedo({
            undo: graph.current.getUndoStack().length,
            redo: graph.current.getRedoStack().length
        })
    }

    /**
     * 添加线
     */
    const onAddEdge = () => {
        // 获取两个点
        let arr = {
            source: "node_" + nodeIndex,
            target: "1",
        };
        addEdge(graph.current, arr);

        setUndoOrRedo({
            undo: graph.current.getUndoStack().length,
            redo: graph.current.getRedoStack().length
        })
    }

    /**
     * 上一步
     */
    const onUndo = () => {
        undo(graph.current);

        setUndoOrRedo({
            undo: graph.current.getUndoStack().length,
            redo: graph.current.getRedoStack().length
        })
    }

    /**
     * 下一步
     */
    const onRedo = () => {
        redo(graph.current);

        setUndoOrRedo({
            undo: graph.current.getUndoStack().length,
            redo: graph.current.getRedoStack().length
        })
    }

    /**
     * 组合
     */
    const onGroup = () => {
        // 获取选中节点
        let selectedNodes = graph.current.findAllByState('node', 'selected');
        // console.log(selectedNodes)
        groupNodes(graph.current, selectedNodes);

        setUndoOrRedo({
            undo: graph.current.getUndoStack().length,
            redo: graph.current.getRedoStack().length
        })
    }
    /**
     * 拆分
     */
    const onUnGroup = () => {
        // 获取选中节点
        let selectedNodes = graph.current.findAllByState('node', 'selected');
        console.log(selectedNodes)
        unGroupNodes(graph.current, selectedNodes);

        setUndoOrRedo({
            undo: graph.current.getUndoStack().length,
            redo: graph.current.getRedoStack().length
        })
    }

    /**
     * 局部：网格布局
     */
    const onGridLayout = () => {
        let selectedNodes = graph.current.findAllByState('node', 'selected');
        let nodes = [];
        selectedNodes.forEach(selectedNode => {
            nodes.push(selectedNode.getModel());
        })
        console.log(nodes)
        if (nodes.length) {
            gridLayout(graph.current, nodes, []);
        } else {
            message.warn("请选择需要布局的点");
        }
    }

    /**
     * 水平布局/垂直布局-局部
     */
    const onDirectionLayout = (e, dir) => {
        let selectedNodes = graph.current.findAllByState('node', 'selected');
        let nodes = [];
        selectedNodes.forEach(selectedNode => {
            nodes.push(selectedNode.getModel());
        })
        if (nodes.length) {
            directionLayout(graph.current, nodes, [], dir)
        } else {
            message.warn("请选择需要布局的点");
        }
    }

    /**
     * 全局： 金字塔布局
     */
    const onDagreLayout = () => {
        dagreLayout(graph.current)
    }

    /**
     * 全局：同心圆布局
     */
    const onConcentricLayout = () => {
        graph.current.updateLayout('concentric');
    }

    /**
     * 全局：智能布局
     */
    const onZnLayout = () => {
        graph.current.updateLayout({
            type: 'fruchterman',
            gravity: 0.5,              // 可选
            speed: 10,                 // 可选
            clustering: false,         // 可选
            clusterGravity: 10,       // 可选
            workerEnabled: true       // 可选，开启 web-worker  }
        });
    }
    

    return (
        <div className="graph-main">
            <div className="graph-menu">
                <div className="graph-menu-item" onClick={onBrushSelect}>框选</div>
                <div className="graph-menu-group">
                    <div className="graph-menu-item" onClick={onAddNode}>添加点</div>
                    <div className="graph-menu-line"></div>
                    <div className="graph-menu-item" onClick={onAddEdge}>添加关系</div>
                </div>
                <div className="graph-menu-group">
                    <div className={`graph-menu-item ${undoOrRedo.undo === 0 ? 'not-click' : ''}`}
                         onClick={onUndo}>上一步
                    </div>
                    <div className="graph-menu-line"></div>
                    <div className={`graph-menu-item ${undoOrRedo.redo === 0 ? 'not-click' : ''}`}
                         onClick={onRedo}>下一步
                    </div>
                </div>
                <div className="graph-menu-group">
                    <div className="graph-menu-item" onClick={onGroup}>组合</div>
                    <div className="graph-menu-line"></div>
                    <div className="graph-menu-item" onClick={onUnGroup}>拆分</div>
                </div>
                <div className="graph-menu-group">
                    <div className="graph-menu-item" onClick={onGridLayout}>矩阵布局</div>
                    <div className="graph-menu-line"></div>
                    <div className="graph-menu-item" onClick={onConcentricLayout}>同心圆布局</div>
                    <div className="graph-menu-line"></div>
                    <div className="graph-menu-item" onClick={onZnLayout}>智能布局</div>
                    <div className="graph-menu-line"></div>
                    <div className="graph-menu-item" onClick={onDagreLayout}>金字塔布局</div>
                    <div className="graph-menu-item" onClick={e => onDirectionLayout(e, 'horizontal')}>水平布局</div>
                    <div className="graph-menu-item" onClick={e => onDirectionLayout(e, 'vertical')}>垂直布局</div>
                </div>
            </div>

            <div className="graph-wrap">
                <div ref={ref} style={{position: 'relative'}}></div>
            </div>
        </div>
    );
}

export default App;
